package com.slipper.common.util;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

import javax.servlet.http.HttpServletResponse;

public final class AttachUtil {
    /**
     * 用于产生唯一文件名的算法，在文件标识相同时做进一步区别的识别流水号
     */
    private static int uniqueFileSequence = 0;

    /**
     * 用于产生唯一文件名的算法，记录上一个产生的文件标识
     */
    private static Date preFileIdentify = null;

    /**
     * 用于产生唯一文件名的算法，用来产生文件名字符串
     */
    private static final SimpleDateFormat FILE_NAME_FORMAT = new SimpleDateFormat("yyyyMMddHHmmssSSS");

    public synchronized static String getUniqueFileName() {
        Date fileIdentify = new Date();
        if (fileIdentify.equals(AttachUtil.preFileIdentify)) {
            AttachUtil.uniqueFileSequence++;
        } else {
            AttachUtil.uniqueFileSequence = 0;
        }
        AttachUtil.preFileIdentify = fileIdentify;
        StringBuilder fileName = new StringBuilder();
        fileName.append(AttachUtil.FILE_NAME_FORMAT.format(fileIdentify));
        if (AttachUtil.uniqueFileSequence > 0) {
            fileName.append(Integer.toString(AttachUtil.uniqueFileSequence, 10));
        }
        return fileName.toString();
    }

    /**
     * 下载附件
     * @param response HttpServletResponse
     * @param fileName 输出的文件名
     * @param savePath 文件所在路径
     * @return null 或者是 错误描述
     */
    public static String downloadAttach(HttpServletResponse response, String fileName, String savePath) {
        BufferedInputStream is = null;
        OutputStream os = null;
        String result = null;
        try {
            response.setContentType("application/octet-stream");
            String trueName = new String(
                    fileName.getBytes(StandardCharsets.UTF_8),
                    StandardCharsets.ISO_8859_1);
            response.setHeader("Content-Disposition", "attachment; filename=\"" + trueName + "\"");
            is = new BufferedInputStream(Files.newInputStream(Paths.get(savePath)));
            os = response.getOutputStream();
            byte[] b = new byte[2048];
            int len;
            while ((len = is.read(b)) > 0) {
                os.write(b, 0, len);
            }
        } catch (IOException ex) {
            // 下载过程中用户取消或其它IO异常
            result = "用户取消下载或其它IO异常" + ex.getMessage();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ex) {
                    result = "关闭输入流异常：" + ex.getMessage();
                }
            }
            if (os != null) {
                try {
                    os.flush();
                } catch (IOException ex) {
                    result = "清空输出缓冲异常：" + ex.getMessage();
                }
                try {
                    os.close();
                } catch (IOException ex) {
                    result = "关闭输出流异常：" + ex.getMessage();
                }
            }
        }

        return result;
    }

    /**
     * 下载模板
     * @param response HttpServletResponse
     * @param template 模板文件名
     */
    public static String downloadTemplate(HttpServletResponse response, String template, String fileName) {
        BufferedInputStream is = null;
        OutputStream os = null;
        String result = null;
        try {
            Tool.beforeExport(response,fileName);
            is = new BufferedInputStream(
                    Objects.requireNonNull(
                            AttachUtil.class
                                    .getClassLoader()
                                    .getResourceAsStream("template/" + template)));
            os = response.getOutputStream();
            byte[] b = new byte[2048];
            int len;
            while ((len = is.read(b)) > 0) {
                os.write(b, 0, len);
            }
        } catch (IOException ex) {
            // 下载过程中用户取消或其它IO异常
            result = "用户取消下载或其它IO异常" + ex.getMessage();
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ex) {
                    result = "关闭输入流异常：" + ex.getMessage();
                }
            }
            if (os != null) {
                try {
                    os.flush();
                } catch (IOException ex) {
                    result = "清空输出缓冲异常：" + ex.getMessage();
                }
                try {
                    os.close();
                } catch (IOException ex) {
                    result = "关闭输出流异常：" + ex.getMessage();
                }
            }
        }

        return result;
    }

    public static InputStream getTplInputStream(String tplName) {
        return AttachUtil.class.getClassLoader().getResourceAsStream("template/" + tplName);
    }

    /*
     * 获取文件扩展名
     */
    public static String getExtension(String filename) {
        if ((filename != null) && (!filename.isEmpty())) {
            int i = filename.lastIndexOf('.');
            if ((i > -1) && (i < (filename.length() - 1))) {
                return filename.substring(i + 1);
            }
        }
        return "";
    }

    /*
     * 拷贝文件
     */
    public static void copyFile(String src, String dest) throws IOException {
        copyFile(new File(src), new File(dest));
    }

    /*
     * 拷贝文件
     */
    public static void copyFile(File src, File dest) throws IOException {
        FileInputStream fis = new FileInputStream(src);
        FileOutputStream fos = new FileOutputStream(dest);
        byte[] temp = new byte[10 * 1024 * 1024];
        int c;
        while ((c = fis.read(temp)) != -1) { // 返回实际读取到的大小
            fos.write(temp, 0, c);
        }
        fos.flush(); // 刷新缓冲区,记得
        fos.close();
        fis.close();
    }

    public static synchronized String getNewDocAffixCode() {
        return (new SimpleDateFormat("yyyyMMddhhmmss")).format(new Date()) + Tool.getRandomString(6);
    }

    public static String getNewDocAffixFileName() {
        return AttachUtil.getNewDocAffixCode();
    }

}
